/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.bff.bjj;

import com.bff.bjj.dao.AlbumDao;
import com.bff.bjj.dao.ArtistDao;
import com.bff.bjj.dao.DatabaseDao;
import com.bff.bjj.dao.GenreDao;
import com.bff.bjj.dao.SongDao;
import com.bff.bjj.dao.YearDao;
import com.bff.bjj.dao.ItemDao;
import com.bff.bjj.dao.SearchDao;
import com.bff.bjj.musicobjects.BJJAlbum;
import com.bff.bjj.musicobjects.BJJArtist;
import com.bff.bjj.musicobjects.BJJDatabaseProgress;
import com.bff.bjj.musicobjects.BJJGenre;
import com.bff.bjj.musicobjects.BJJPlayableItem;
import com.bff.bjj.musicobjects.BJJSearchResult;
import com.bff.bjj.musicobjects.BJJSong;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * Interface implemented by a server database;
 * @author Bill
 */
public class BJJDatabase {
    @Autowired
    private SongDao songDao;
    @Autowired
    private AlbumDao albumDao;
    @Autowired
    private ArtistDao artistDao;
    @Autowired
    private YearDao yearDao;
    @Autowired
    private GenreDao genreDao;
    @Autowired
    private DatabaseDao databaseDao;
    @Autowired
    private ItemDao itemDao;
    @Autowired
    private SearchDao searchDao;
    /**
     * Returns a {@code Collection} of new music {@link BJJAlbum}s.  This method 
     * does not populate the artist field so an additional call is necessary if you 
     * need that field later on.
     *
     * Use {@link getAlbums(boolean) if you with to populate the artist field.
     *
     * @return a {@code Collection} of all {@link BJJAlbum}s
     */
    public Collection<BJJAlbum> getNewMusic() {
        return albumDao.getNewMusic();
    }
    
    /**
     * Returns the total number of songs
     *
     * @return the number of songs
     * @throws BJJException if there is a problem getting the count
     */
    public int getSongCount() {
        return songDao.getSongCount();
    }

    /**
     * Returns the total number of albums
     *
     * @return the number of albums
     * @throws BJJException if there is a problem getting the count
     */
    public int getAlbumCount() {
        return albumDao.getAlbumCount();
    }

    /**
     * Returns the total number of artists
     *
     * @return the number of artists
     * @throws BJJException if there is a problem getting the count
     */
    public int getArtistCount() {
        return artistDao.getArtistCount();
    }

    /**
     * Returns the total number of genres
     *
     * @return the number of genres
     * @throws BJJException if there is a problem getting the count
     */
    public int getGenreCount() {
        return genreDao.getGenreCount();
    }

    /**
     * Searches albums, artists, and titles for the search criteria.
     *
     * @param criteria
     * @return a collection of {@link BJJArtist}, {@link BJJAlbum}, and {@link BJJSong}
     * @throws BJJDatabaseException if there is a database problem
     */
    public BJJSearchResult searchAll(String criteria) {
        return searchDao.searchAll(criteria);
    }

    /**
     * Returns a <CODE>Collection</CODE> of <CODE>BJJArtist</CODE>s for an any
     * artist containing the parameter artist.
     *
     * @param criteria the search criteria
     * @return a <CODE>Collection</CODE> of {@link BJJSong}s
     * @throws BJJDatabaseException if there is a database problem
     */
    public Collection<BJJArtist> searchArtists(String criteria) {
        return searchDao.searchArtists(criteria);
    }
    
    /**
     * Returns a <CODE>Collection</CODE> of <CODE>BJJSong</CODE>s for an any
     * album containing the parameter album.
     *
     * @return a <CODE>Collection</CODE> of {@link BJJSong}s
     * @throws BJJDatabaseException if there is a database problem
     * @param criteria the album to match
     */
    public Collection<BJJAlbum> searchAlbums(String criteria) {
        return searchDao.searchAlbums(criteria);
    }

    /**
     * Returns a <CODE>Collection</CODE> of <CODE>BJJSong</CODE>s for an any
     * title containing the parameter title.
     *
     * @return a <CODE>Collection</CODE> of {@link BJJSong}s
     * @throws BJJDatabaseException if there is a database problem
     * @param criteria the search criteria
     */
    public Collection<BJJSong> searchTitles(String criteria) {
        return searchDao.searchTitles(criteria);
    }

    /**
     * Returns a <CODE>Collection</CODE> of {@link BJJAlbum}s for an artist
     *
     * @param artist
     * @return a <CODE>Collection</CODE> of {@link BJJAlbum}s
     * @throws BJJDatabaseException if there is a database problem
     */
    public Collection<BJJAlbum> listAlbumsForArtist(BJJArtist artist) {
        return albumDao.listAlbumsForArtist(artist);
    }
    /**
     * Returns a <CODE>Collection</CODE> of {@link BJJAlbum}s for an artist
     *
     * @param artist
     * @return a <CODE>Collection</CODE> of {@link BJJAlbum}s
     * @throws BJJDatabaseException if there is a database problem
     */
    public Collection<BJJAlbum> listAlbumsForYear(String year) {
        return albumDao.listAlbumsForYear(year);
    }
    /**
     * Returns a <CODE>Collection</CODE> of {@link BJJAlbum}s for an artist
     *
     * @param artist
     * @return a <CODE>Collection</CODE> of {@link BJJAlbum}s
     * @throws BJJDatabaseException if there is a database problem
     */
    public Collection<BJJAlbum> listAlbumsForGenre(BJJGenre genre) {
        return albumDao.listAlbumsForGenre(genre);
    }

    /**
     * Lists the albums for the passed criteria. Pass null to match all.
     *
     * @param artist the @{link BJJArtist} to match
     * @param genre the @{link BJJGenre} to match
     * @param year the year to match
     * @return a <CODE>Collection</CODE> of {@link BJJAlbum}s
     * @throws BJJDatabaseException if there is a database problem
     */
    public Collection<BJJAlbum> listAlbums(BJJArtist artist, BJJGenre genre, String year) {
        return albumDao.listAlbums(artist, genre, year);
    }

    /**
     * Returns a {@code Collection} of {@link BJJArtist}s for a given
     * {@link BJJGenre}
     *
     * @param genre the {@link BJJGenre} to match
     * @return a {@code Collection} of {@link BJJArtist}s
     * @throws BJJDatabaseException if there is a database problem
     */
    public Collection<BJJArtist> listArtistsForGenre(BJJGenre genre) {
        return artistDao.listArtistsForGenre(genre);
    }

    /**
     * Returns a {@link BJJArtist} for a {@link BJJAlbum}
     *
     * @param album
     *            the {@link BJJAlbum} to lookup
     * @return the {@link BJJArtist} for the album
     * @throws BJJDatabaseException
     *             if there is a database problem
     */
    public Collection<BJJArtist> getArtistsForAlbum(BJJAlbum album) {
        return artistDao.getArtistsForAlbum(album);
    }

    /**
     * Returns a {@code Collection} of {@link BJJSong}s for a given
     * {@link BJJArtist}
     *
     * @param artist
     *            the {@link BJJArtist} to look up
     * @return a {@code Collection} of {@link BJJSong}s
     * @throws BJJDatabaseException
     */
    public Collection<BJJSong> listSongsForArtist(BJJArtist artist) {
        return songDao.listSongsForArtist(artist);
    }

    public Collection<BJJSong> listSongsForYear(String year) {
        return songDao.listSongsForYear(year);
    }

    public Collection<BJJSong> listSongsForGenre(BJJGenre genre) {
        return songDao.listSongsForGenre(genre);
    }  

    /**
     * Returns a <code>Collection</code> of {@link BJJSong}s for a given
     * {@link BJJAlbum}
     *
     * @param album the {@link BJJAlbum}
     * @return a <code>Collection</code> of {@link BJJSong}s
     */
    public Collection<BJJSong> listSongsForAlbum(BJJAlbum album) {
        return songDao.listSongsForAlbum(album);
    }

    /**
     * Returns the {@link BJJSong} for a song id. Returns <code>null</code> if
     * there is not a match.
     *
     * @param songId the song id
     * @return the {@link BJJSong}
     */
    public BJJPlayableItem lookupItem(String songId) {
        return itemDao.lookupItem(songId);
    }
    
    /**
     * Returns the {@link BJJSong} for a song id. Returns <code>null</code> if
     * there is not a match.
     *
     * @param songId
     *            the song id
     * @return the {@link BJJSong}
     */
    public BJJSong lookupSong(String songId) {
        return songDao.lookupSong(songId);
    }

    /**
     * Returns the {@link BJJSong} for a song id. Returns <code>null</code> if
     * there is not a match. This will return null for remote streams.
     *
     * @param url the song url
     * @return the {@link BJJSong}
     */
    public BJJPlayableItem lookupItemByUrl(String url) {
        return itemDao.lookupItemByUrl(url);
    }

    /**
     * Returns the progress of the database scan. Progress results are stored in
     * a {@link BJJDatabaseProgress} object.
     *
     * @return a {@link BJJDatabaseProgress} containing scan results
     */
    public BJJDatabaseProgress getScanProgress() {
        return databaseDao.getScanProgress();
    }  

    /**
     * Scans music directory for new or changed music
     */
    public void rescan() {
        databaseDao.rescan();
    }

    /**
     * Clears the database and scans the music directory
     */
    public void clearDatabaseAndRescan() {
        databaseDao.clearDatabaseAndRescan();
    }
    
    /**
     * Returns true if the database is rescanning, false if not
     *
     * @return true if rescanning, false otherwise
     */
    public boolean isRescanning() {
        return databaseDao.isRescanning();
    }

    /**
     * Returns a {@code Collection} of all {@link BJJGenre}s
     *
     * @return a {@code Collection} of all {@link BJJGenre}s
     */
    public Collection<BJJGenre> getGenres() {
        return genreDao.getGenres();
    }

    /**
     * Returns a {@code Collection} of all {@link BJJArtist}s
     *
     * @return a {@code Collection} of all {@link BJJArtist}s
     */
    public Collection<BJJArtist> getArtists() {
        return artistDao.getArtists();
    }
    
    /**
     * Returns a {@code Collection} of all {@link BJJAlbum}s.  This method does not populate
     * the artist field so an additional call is necessary if you need that field later on.
     *
     * Use {@link getAlbums(boolean) if you with to populate the artist field.
     *
     * @return a {@code Collection} of all {@link BJJAlbum}s
     */
    public Collection<BJJAlbum> getAlbums() {
        return albumDao.getAlbums();
    }

    /**
     * Returns a {@code Collection} of all {@link BJJAlbum}s include the artist name 
     * associated with the album.  Passing true slightly affects the performance of the lookup.
     * @param includeArtist
     * @return a {@code Collection} of all {@link BJJAlbum}s
     */
    public Collection<BJJAlbum> getAlbums(boolean includeArtist) {
        return albumDao.getAlbums(includeArtist);
    }  

    /**
     * Returns a {@code Collection} of all years
     *
     * @return a {@code Collection} of all years
     */
    public Collection<String> getYears() {
        return yearDao.getYears();
    }
}
